import json
import os.path
import time
import pathlib

from django.shortcuts import render
from django.core import serializers
from django.http import JsonResponse, FileResponse, HttpResponse
from django.db.models import QuerySet
from django.db.models import Count, Sum
from datetime import datetime
from Crypto.Cipher import AES
from django.core.paginator import Paginator
from Crypto.Util.Padding import pad, unpad
from Crypto.Random import get_random_bytes
from django.utils.encoding import smart_str

from dataQuery.models import *


# Create your views here.
class ImageCrypto(object):
    def __init__(self, file_path, file_name, file_format):
        self.file_path = pathlib.Path(file_path)
        self.file_name = file_name
        self.file_format = file_format
        self.key = get_random_bytes(16)
        self.iv = get_random_bytes(16)

    def image_encrypt(self):
        cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
        with open(self.file_path.joinpath(self.file_name + f'.{self.file_format}'), 'rb') as file:
            plaintext = file.read()
            ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
        with open(self.file_path.joinpath(self.file_name + '_encrypted.' + self.file_format), 'wb') as file:
            file.write(cipher.iv + ciphertext)

    def image_decrypt(self):
        with open(self.file_path.joinpath(self.file_name + '_encrypted.' + self.file_format), 'rb') as file:
            ciphertext = file.read()
            iv = ciphertext[:16]
            ciphertext = ciphertext[16:]
            cipher = AES.new(self.key, AES.MODE_CBC, iv)
            plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
        with open(self.file_path.joinpath(self.file_name + '_decrypted.' + self.file_format), 'wb') as file:
            file.write(plaintext)


def contraband_add(check_time, check_place, item_name, original_img_path, detected_img_path):
    err_info = ''
    add_status = True

    try:
        contraband = ContrabandImage(time=check_time,
                                     place=check_place,
                                     name=item_name,
                                     original_img_path=original_img_path,
                                     detected_img_path=detected_img_path)
        contraband.save()
    except Exception as e:
        err_info = e.__str__()
        add_status = False

    result_dict = {"res": add_status,
                   "msg": err_info}

    return JsonResponse(result_dict)


def contraband_update(request, item, old_info, new_info):
    err_info = ''
    update_status = True

    try:
        ContrabandImage.objects.filter(item=old_info).update(item=new_info)
    except Exception as e:
        err_info = e.__str__()
        update_status = False

    result_dict = {"res": update_status,
                   "msg": err_info}

    return JsonResponse(result_dict)


def contraband_delete(request):
    params = request.body
    # 将 JSON 字符串（JSON 序列化的数据）解析为对应的 Python 对象，此时还是字典的形式
    item_ids: list = json.loads(params)['idArray']
    err_info = ''
    delete_status = True

    try:
        for item_id in item_ids:
            ContrabandImage.objects.filter(item_id=item_id).delete()
    except Exception as e:
        print('error: {}'.format(e.__str__()))
        err_info = e.__str__()
        delete_status = False
    if delete_status:

        code = 200
    else:
        code = 500
    result_dict = {
        "code": code,
        "res": delete_status,
        "message": err_info}

    return JsonResponse(result_dict)


def contraband_select(request):
    params = request.body
    temp: dict = json.loads(params)
    param_dict: dict = temp['condition']
    valid_dict = {}
    time_range = {}
    for param_key in param_dict:
        if param_dict[param_key] != '' and 'Time' not in param_key:
            valid_dict.setdefault(param_key, param_dict[param_key])
        # 单独调出startTime和endTime放入time_range
        elif param_dict[param_key] != '' and 'Time' in param_key:
            time_range.setdefault(param_key, param_dict[param_key])

    err_info = ''
    select_status = True
    record: dict = {}

    try:
        # 不指定条件则查询所有记录
        if len(valid_dict) == 0 and len(time_range) == 0:
            record: QuerySet = ContrabandImage.objects.filter().all()
        elif len(valid_dict) != 0 and len(time_range) == 0:
            record: QuerySet = ContrabandImage.objects.filter(**valid_dict)
        else:
            if len(time_range) == 1 and 'startTime' in time_range.keys():
                record: QuerySet = (ContrabandImage.objects.filter(**valid_dict).
                                    filter(time__gte=int(time_range['startTime'])))
            elif len(time_range) == 1 and 'endTime' in time_range.keys():
                record: QuerySet = (ContrabandImage.objects.filter(**valid_dict).
                                    filter(time__lte=int(time_range['endTime'])))
            elif len(time_range) > 1:
                record: QuerySet = (ContrabandImage.objects.filter(**valid_dict).
                                    filter(time__gte=int(time_range['startTime']),
                                           time__lte=int(time_range['endTime'])))
    except Exception as e:
        err_info = e.__str__()
        select_status = False

    data = json.dumps(record) if isinstance(record, dict) else json.dumps(list(record.values()))
    if select_status:
        code = 200
    else:
        code = 500
    result_dict = {"code": code,
                   "data": data,
                   "message": err_info}

    return record, result_dict, JsonResponse(result_dict)


def contraband_count(request):
    params = request.body
    param_dict: dict = json.loads(params)
    valid_dict, time_range = {}, {}
    for param_key in param_dict:
        if param_dict[param_key] != '' and 'Time' not in param_key:
            valid_dict.setdefault(param_key, param_dict[param_key])
        elif param_dict[param_key] != '' and 'Time' in param_key:
            time_range.setdefault(param_key, param_dict[param_key])

    count = 0
    err_info = ''

    try:
        if len(valid_dict) == 0 and len(time_range) == 0:
            count = ContrabandImage.objects.all().count()
        elif len(valid_dict) != 0 and len(time_range) == 0:
            count = ContrabandImage.objects.filter(**valid_dict).values('name', 'place').count()
        else:
            if len(time_range) == 1 and 'startTime' in time_range.keys():
                count = (ContrabandImage.objects.filter(**valid_dict).values('name', 'place').
                         filter(time__gte=int(time_range['startTime'])).count())
            elif len(time_range) == 1 and 'endTime' in time_range.keys():
                count = (ContrabandImage.objects.filter(**valid_dict).values('name', 'place').
                         filter(time__lte=int(time_range['endTime'])).count())
            elif len(time_range) > 1:
                count = (ContrabandImage.objects.filter(**valid_dict).values('name', 'place').
                         filter(time__gte=int(time_range['startTime']),
                                time__lte=int(time_range['endTime'])).count())
    except Exception as e:
        err_info = e.__str__()

    result_dict = {"num of all records": count}

    print(result_dict)

    return JsonResponse(result_dict)


def contraband_statistic(request):
    params = request.body
    param_dict = json.loads(params)
    start, end, fmt = '', '', '%Y-%m-%d %H:%M:%S'
    name_req, place_req, time_req = {}, {}, {}
    valid_dict, time_range = {}, {}
    for param_key in param_dict:
        if param_dict[param_key] != '' and 'Time' not in param_key:
            valid_dict.setdefault(param_key, param_dict[param_key])
        elif param_dict[param_key] != '' and 'Time' in param_key:
            time_range.setdefault(param_key, param_dict[param_key])

    record = {}
    err_info = ''

    try:
        # 不指定条件则查询所有记录
        if len(valid_dict) == 0 and len(time_range) == 0:
            record: QuerySet = ContrabandImage.objects.filter().all()
        elif len(valid_dict) != 0 and len(time_range) == 0:
            record: QuerySet = ContrabandImage.objects.filter(**valid_dict).values('name', 'place')
        else:
            if len(time_range) == 1 and 'startTime' in time_range.keys():
                record: QuerySet = (ContrabandImage.objects.filter(**valid_dict).values('name', 'place').
                                    filter(time__gte=int(time_range['startTime'])))
            elif len(time_range) == 1 and 'endTime' in time_range.keys():
                record: QuerySet = (ContrabandImage.objects.filter(**valid_dict).values('name', 'place').
                                    filter(time__lte=int(time_range['endTime'])))
            elif len(time_range) > 1:
                record: QuerySet = (ContrabandImage.objects.filter(**valid_dict).values('name', 'place').
                                    filter(time__gte=int(time_range['startTime']),
                                           time__lte=int(time_range['endTime'])))
    except Exception as e:
        print(e.__str__())

    # if 'startTime' in time_range.keys() and 'endTime' not in time_range.keys():
    #     start = time.strftime(fmt, time.localtime(int(time_range['startTime'])))
    # elif 'endTime' in time_range.keys() and 'startTime' not in time_range.keys():
    #     end = time.strftime(fmt, time.localtime(int(time_range['endTime'])))
    # elif 'startTime' in time_range.keys() and 'endTime' in time_range.keys():
    #     start = time.strftime(fmt, time.localtime(int(time_range['startTime'])))
    #     end = time.strftime(fmt, time.localtime(int(time_range['endTime'])))

    stat_res = record.values('name').annotate(count=Count('name')).all()
    for item in stat_res:
        name_req.setdefault(item['name'], item['count'])
    stat_res = record.values('place').annotate(count=Count('place')).all()
    for item in stat_res:
        place_req.setdefault(item['place'], item['count'])

    # if start != '' and end == '':
    #     stat_res = (ContrabandImage.objects.values('time').
    #                 filter(time__gte=param_dict['startTime'])).annotate(count=Count('time')).all()
    #     for item in stat_res:
    #         time_key = time.strftime(fmt, time.localtime(item['time']))
    #         time_req.setdefault(str(datetime.strptime(time_key, fmt).date()), 0)
    #         time_req[str(datetime.strptime(time_key, fmt).date())] += item['count']
    # elif start == '' and end != '':
    #     stat_res = (ContrabandImage.objects.values('time').
    #                 filter(time__lte=param_dict['endTime'])).annotate(count=Count('time')).all()
    #     for item in stat_res:
    #         time_key = time.strftime(fmt, time.localtime(item['time']))
    #         time_req.setdefault(str(datetime.strptime(time_key, fmt).date()), 0)
    #         time_req[str(datetime.strptime(time_key, fmt).date())] += item['count']
    # elif start and end:
    #     stat_res = (ContrabandImage.objects.values('time').
    #                 filter(time__gte=param_dict['startTime'], time__lte=param_dict['endTime']).
    #                 annotate(count=Count('time')).all())
    #     for item in stat_res:
    #         time_key = time.strftime(fmt, time.localtime(item['time']))
    #         time_req.setdefault(str(datetime.strptime(time_key, fmt).date()), 0)
    #         time_req[str(datetime.strptime(time_key, fmt).date())] += item['count']
    # else:
    stat_res = record.values('time').annotate(count=Count('time')).all()
    for item in stat_res:
        time_key = time.strftime(fmt, time.localtime(item['time']))
        time_req.setdefault(str(datetime.strptime(time_key, fmt).date()), 0)
        time_req[str(datetime.strptime(time_key, fmt).date())] += item['count']

    result_dict = {'name': name_req, 'place': place_req, 'time': time_req}

    result_dict = {"code": 200,
                   "data": result_dict,
                   "message": err_info}
    print(result_dict)
    return JsonResponse(result_dict)


# 分页查询
def contraband_select_paginate(request):
    """
    参数说明:
    * request: 前端请求
        .body:
            - condition: 查询条件
            - page: 待查页号
            - per_page: 每页数据数量
    """
    params = request.body
    params_dict = json.loads(params)
    page_info_dict = params_dict['page_info']

    result, result_dict, _ = contraband_select(request)
    paginator = Paginator(object_list=result, per_page=page_info_dict['per_page'], )
    records = paginator.get_page(page_info_dict['page'])
    pages = paginator.num_pages

    data = []
    for item in json.loads(serializers.serialize("json", records.object_list)):
        item["fields"]["item_id"] = item["pk"]
        data.append(item["fields"])
    data = json.dumps(data)
    # 返回总条目数
    total = paginator.count
    result_dict = {
        "code": result_dict['code'],
        "data": data,
        "pages": pages,
        "total": total,
        "message": result_dict['message']
    }

    return JsonResponse(result_dict)


# 实现导出
def getImageByPath(request):
    image_path = request.GET.get('path')
    print(image_path)
    with open(image_path, 'rb') as f:
        image_data = f.read()
    response = HttpResponse(image_data, content_type='image/jpeg')
    return response
